/*
 * igo: com.cctv.igo.admin.scheduler.service.ScheduleService.java Create On 2011-5-3 下午08:29:08 By Q-Wang
 * $Revision: 1.2 $
 */
package com.ctvit.scheduler.service;

import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.quartz.JobDetail;
import org.quartz.SchedulerException;
import org.quartz.Trigger;

import com.ctvit.scheduler.common.SchedulerQueries;
import com.ctvit.scheduler.domain.QrtxTask;
import com.ctvit.scheduler.domain.QrtxTrigger;
import com.ctvit.scheduler.dto.ScheduledTask;
import com.ctvit.scheduler.dto.Task;
import com.ctvit.scheduler.dto.TaskTypeDefinition;
import com.ctvit.scheduler.dto.TriggerTypeDefinition;
import com.ctvit.scheduler.parser.DefaultTaskParser;
import com.ctvit.scheduler.parser.DefaultTriggerParser;
import com.ctvit.scheduler.parser.TaskParser;
import com.ctvit.scheduler.parser.TriggerManager;
import com.ctvit.scheduler.parser.TriggerParser;
import com.ctvit.framework.schedule.SchedulerManager;
import com.ctvit.framework.service.BaseService;
import com.ctvit.framework.web.context.ContextHolder;

/**
 * @author <a href="mailto:apeidou@gmail.com">Q-Wang</a>
 * 
 */
public class ScheduleService extends BaseService {

	public Map<String, TaskTypeDefinition> getTaskTypeDefinition() {
		List<TaskTypeDefinition> types = genericDao.queryBySqlID(SchedulerQueries.SELECT_TASK_TYPES, null);
		Map<String, TaskTypeDefinition> taskTypes = new HashMap<String, TaskTypeDefinition>();
		for (TaskTypeDefinition type : types) {
			taskTypes.put(type.getType(), type);
			String parser = type.getParser();
			if (StringUtils.isEmpty(parser)) {
				type.setParserInstance(new DefaultTaskParser());
			} else {
				try {
					Class<?> clazz = Class.forName(parser);
					if (clazz.isAssignableFrom(TaskParser.class)) {
						Object parserInstance = clazz.newInstance();
						type.setParserInstance((TaskParser) parserInstance);
					} else {
						throw new IllegalStateException("");
					}
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
					throw new IllegalStateException("");
				} catch (InstantiationException e) {
					e.printStackTrace();
					throw new IllegalStateException("");
				} catch (IllegalAccessException e) {
					e.printStackTrace();
					throw new IllegalStateException("");
				}
			}
		}
		return taskTypes;
	}

	public Map<String, TriggerTypeDefinition> getTriggerTypeDefinition() {
		List<TriggerTypeDefinition> types = genericDao.queryBySqlID(SchedulerQueries.SELECT_TRIGGER_TYPES, null);
		Map<String, TriggerTypeDefinition> triggerTypes = new HashMap<String, TriggerTypeDefinition>();
		for (TriggerTypeDefinition type : types) {
			triggerTypes.put(type.getType(), type);
			String parser = type.getParser();
			if (StringUtils.isEmpty(parser)) {
				type.setParserInstance(new DefaultTriggerParser());
			} else {
				try {
					Class<?> clazz = Class.forName(parser);
					if (clazz.isAssignableFrom(TriggerParser.class))  {
						Object parserInstance = clazz.newInstance();
						type.setParserInstance((TriggerParser) parserInstance);
					} else {
						throw new IllegalStateException("");
					}
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
					throw new IllegalStateException("");
				} catch (InstantiationException e) {
					e.printStackTrace();
					throw new IllegalStateException("");
				} catch (IllegalAccessException e) {
					e.printStackTrace();
					throw new IllegalStateException("");
				}
			}
		}
		return triggerTypes;
	}

	public List<ScheduledTask> listScheduledTaskDetails(Long triggerId) {
		return genericDao.queryBySqlID(SchedulerQueries.SELECT_TRIGGER_TASK_DETAILS, triggerId);
	}

	public ScheduledTask getScheduledTask(Long triggerId, Long taskId) {
		ScheduledTask query = new ScheduledTask();
		query.setTriggerId(triggerId);
		query.setTaskId(taskId);
		List<ScheduledTask> tasks = genericDao.queryBySqlID(SchedulerQueries.SELECT_SCHEDULED_TASK, query);
		if (tasks.isEmpty()) {
			return null;
		}
		ScheduledTask scheduledTask = tasks.get(0);
		Task task = new Task(genericDao.getById(QrtxTask.class, taskId));
		scheduledTask.setTask(task);
		return scheduledTask;
	}

	public void updateScheduledTask(ScheduledTask scheduledTask) {
		scheduledTask.setModifier(ContextHolder.getCurrentUser());
		scheduledTask.setModifyTimestamp(new Date());
		genericDao.updateBySqlID(SchedulerQueries.UPDATE_SCHEDULED_TASK, scheduledTask);
	}

	public void addTaskToTrigger(Long taskId, Long triggerId) {
		ScheduledTask task = new ScheduledTask(taskId, triggerId);
		task.setCreator(ContextHolder.getCurrentUser());
		task.setCreateTimestamp(new Date());
		task.setModifier(null);
		task.setModifyTimestamp(null);
		genericDao.insertBySqlID(SchedulerQueries.ADD_SCHEDULED_TASK, task);
	}

	public void removeTaskFromTrigger(Long taskId, Long triggerId) {
		ScheduledTask task = new ScheduledTask(taskId, triggerId);
		genericDao.deleteBySqlID(SchedulerQueries.REMOVE_SCHEDULED_TASK, task);
	}

	public void initializeSchedule() {
		List<QrtxTrigger> triggers = genericDao.getByCondition(QrtxTrigger.class, null, null);
		for (QrtxTrigger qrtxTrigger:triggers) {
			List<ScheduledTask> scheduledTasks = genericDao.queryBySqlID(SchedulerQueries.SELECT_SCHEDULED_TASK_BY_TRIGGER, qrtxTrigger.getId());
			Trigger trigger = null;
			try {
				trigger = TriggerManager.parse(qrtxTrigger);
			} catch (ParseException e) {
				e.printStackTrace();
				continue;
			}
			for (ScheduledTask scheduledTask:scheduledTasks) {
				Task task = new Task(genericDao.getById(QrtxTask.class, scheduledTask.getTaskId()));
				JobDetail detail = task.createJob();
				try {
					if(detail!=null){
						SchedulerManager.scheduleJob(trigger, detail);
					}
				} catch (SchedulerException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
